home *** CD-ROM | disk | FTP | other *** search
/ NetNews Offline 2 / NetNews Offline Volume 2.iso / news / comp / lang / c-part1 / 703 < prev    next >
Encoding:
Internet Message Format  |  1996-08-05  |  4.4 KB

  1. Path: news.rrz.uni-hamburg.de!rzdspc1!simmons
  2. From: simmons@rzdspc1.informatik.uni-hamburg.de (Geoffrey Simmons)
  3. Newsgroups: comp.lang.c,comp.databases,comp.unix.programmer
  4. Subject: Aligning struct fields with NDBM (was: Casting unsigned short ...)
  5. Followup-To: comp.unix.programmer,comp.databases
  6. Date: 8 Jan 96 15:59:55 GMT
  7. Organization: University of Hamburg -- Germany
  8. Message-ID: <simmons.821116795@rzdspc1>
  9. References: <simmons.820857453@rzdspc1>
  10. NNTP-Posting-Host: rzdspc1.informatik.uni-hamburg.de
  11.  
  12. Thanks to everyone who responded publicly and privately to my post
  13. "Casting unsigned short as unsigned int -> Bus error" on comp.lang.c
  14. and gnu.gcc.help. As it turns out, my problem has nothing to do with
  15. the business about casting, and I suspect it has to do with aligning
  16. the struct fields of data fetched by the Unix NDBM database library.
  17. Thus it is probably not a C language problem, which is why I've the changed
  18. the Subject:, Newsgroups:, and Followup-To: lines.
  19.  
  20. Recapping the problem (this is with GCC 2.7.2 on a Sparcstation running
  21. SunOS 4.1.4): I am using NDBM to fetch data for a struct whose fields are
  22. declared as follows. There's no error fetching the data or allocating
  23. memory for the struct:
  24.  
  25.     #include <ndbm.h>
  26.     typedef struct {
  27.         char str1[10];
  28.         char str2[10];
  29.         unsigned char c;
  30.         unsigned short short1;
  31.         unsigned short short2;
  32.         time_t mytime;
  33.         } RecType;
  34.  
  35.     RecType *MyRec;
  36.     datum aKey, theDatum;
  37.     char key[] = "theKey";
  38.  
  39.     aKey.dptr = &key[0];
  40.     aKey.dsize = strlen(key) + 1;
  41.     theDatum = dbm_fetch(dataFile, aKey);
  42.     if (theDatum.dptr == NULL)
  43.         {
  44.           fprintf(stderr, "Data not found\n");
  45.           exit(1);                    /* No error here */
  46.         }
  47.     if ((MyRec = (RecType *) malloc(theDatum.dsize)) == NULL)
  48.         {
  49.           fprintf(stderr, "Error allocting memory\n");
  50.           exit(1);                    /* No error here */
  51.         }
  52.     MyRec = (RecType *) theDatum.dptr;
  53.  
  54. At this point I can use the debugger (GDB 4.15.1) to examine all the data
  55. pointed to by MyRec, and see everything that I expect in all of the struct
  56. fields:
  57.  
  58.     (gdb) print *MyRec
  59.     $1 = {short1 = 1000, short2 = 1000, c = 75 'K',
  60.      mytime = 289104235, str1 = "String1\000\000\000",
  61.      str2 = "String2\000\000\000"}
  62.     (gdb) print MyRec->short1
  63.     $2 = 1000
  64.  
  65. I can also print the character-type fields using printf without problems:
  66.  
  67.     printf("str1 = %s\n", MyRec->str1);
  68.     printf("str2 = %s\n", MyRec->str2);
  69.     printf("c = %c\n", MyRec->c);        /* No problem */
  70.  
  71. But when I try to dereference any of the integer-type members, I get bus
  72. errors:
  73.  
  74.     unsigned short myshort;
  75.  
  76.     myshort = MyRec->short1;            /* Bus error! */
  77.     myshort = MyRec->short2;            /* Bus error! */
  78.     printf("mytime = %ul\n", MyRec->mytime);    /* Bus error! */
  79.  
  80. I conclude from all this that memory allocation for the struct is not the
  81. problem, but suspect that the NDBM fetch is not aligning data in memory
  82. properly (there are warnings about this in the comp.lang.c FAQ and the
  83. free-databases FAQ).
  84.  
  85. I've tried some hacks like using the offsetof() macro to access the
  86. problematic fields as described in the C-faq, and even reordering the
  87. fields in the struct declaration, but get the same problem every time.
  88.  
  89. On the advice of some respondents to my last post, I have added
  90. printf("%x\n", MyRec); to the program after each reference in which MyRec
  91. is involved (SunOS lets you do that). It doesn't show the address changing
  92. anywhere, so it doesn't appear that the pointer is being stomped on. It
  93. *does* show odd-numbered addresses, which some other respondents also
  94. suggested as a cause of the problem. But if that is the problem, why would
  95. I be able to access the character data, but not the integer data? And what
  96. would cause malloc() to allocate an illegal address in the first place?
  97.  
  98. It puzzles me that the debugger can dereference all these fields without
  99. any of the problems that the running program has. As someone pointed out,
  100. memory is different when the debugger's in there with the program. The
  101. debugger does, however, encounter the SIGBUS error when the program reaches
  102. the troublesome line, even though the debugger itself has no problem
  103. accessing the data that the program crashes on. I still find this very
  104. strange.
  105.  
  106. Is this a well-known problem with NDBM, with a well-known solution? I sure
  107. hope so.
  108.  
  109. Thanks,
  110. Geoff
  111. -- 
  112. Geoffrey Simmons     |  simmons@informatik.uni-hamburg.de    | "Insert wise
  113. University of Hamburg     |    Phone: (++49 40) 54715-381    |  and witty
  114. Vogt-Koelln-Str. 30     |    Fax:   (++49 40) 54715-385    |  quotation
  115. D-22527 Hamburg, Germany |                    |  here."
  116.